package com.message;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;

/**
 * Created by Mars on 2017/9/26.
 */

public class RecBufferQueue {
    private static final int MAX_MSG_PACKET_SIZE = 64 * 1024;

    public ByteBuffer mbb = null;
    public ArrayList<byte[]> mArrayList = null;

    public RecBufferQueue() {
        this(UserClient.MAX_READ_BUFFER_SIZE + MAX_MSG_PACKET_SIZE);
    }

    public RecBufferQueue(int nMaxReadBufferSize) {
        mArrayList = new ArrayList<>();
        mbb = ByteBuffer.allocate(nMaxReadBufferSize + MAX_MSG_PACKET_SIZE); //Network.RECEIVE_LEN + MAX_MSG_PACKET_SIZE
//		mbb = ByteBuffer.allocateDirect(nMaxReadBufferSize + MAX_MSG_PACKET_SIZE); //Network.RECEIVE_LEN + MAX_MSG_PACKET_SIZE
        //mbb.order(ByteOrder.LITTLE_ENDIAN);
        mbb.order(ByteOrder.nativeOrder());
    }

    public synchronized void put(byte in[], int nLen) {
        if (nLen <= 0) {
            return;
        }

        mbb.put(in, 0, nLen);

        int bbLen = mbb.position();

        //Length of MsgHead
        if (bbLen < MsgHead.HEAD_SIZE) {
            return;
        }

        mbb.position(0);

        byte name[] = new byte[2];
        mbb.get(name);
        byte ucheadLen = mbb.get();
        mbb.get();
        mbb.getShort();
        //byte uclientType = mbb.get();
        //short usMsgType = mbb.getShort();
        //short usBodyLen = DataTypeUtil.swap(mbb.getShort());
        int usBodyLen = (int) mbb.getChar();

        int nMsgSize = ucheadLen + usBodyLen;

        if (bbLen < nMsgSize) {
            mbb.position(bbLen);

            return;
        }

        int nOffset = 0;
        byte b0[] = new byte[bbLen];

        mbb.position(0);
        mbb.get(b0);

        mbb.position(0);

        while (true) {
            if (bbLen < MsgHead.HEAD_SIZE) {
                mbb.position(bbLen);

                break;
            }

            name = new byte[2];
            mbb.get(name);
            ucheadLen = mbb.get();
            mbb.get();
            mbb.getShort();
            //uclientType = mbb.get();
            //usMsgType = mbb.getShort();
            //usBodyLen = DataTypeUtil.swap(mbb.getShort());
//			usBodyLen = mbb.getShort();
            usBodyLen = mbb.getChar();
            nMsgSize = ucheadLen + usBodyLen;
            mbb.position(0);

            if (bbLen >= nMsgSize) {
                byte b[] = new byte[nMsgSize];

                mbb.position(0);
                mbb.get(b);
                mArrayList.add(b);

                //XUtil.LogI(getClass().getSimpleName(), "put-ucMsgType="
                //		+ ucMsgType + ", mnMsgSize=" + mnMsgSize);

                bbLen -= nMsgSize;
                nOffset += nMsgSize;

                mbb.clear();

                if (bbLen > 0) {
                    mbb.put(b0, nOffset, bbLen);

                    if (bbLen < MsgHead.HEAD_SIZE) {
                        break;
                    }

                    mbb.position(0);

                    mbb.get(name);
                    ucheadLen = mbb.get();
                    mbb.get();
                    mbb.getShort();
                    //uclientType = mbb.get();
                    //usMsgType = mbb.getShort();
                    //usBodyLen = DataTypeUtil.swap(mbb.getShort());
//					usBodyLen = mbb.getShort();
                    usBodyLen = mbb.getChar();

                    nMsgSize = ucheadLen + usBodyLen;

                    if (bbLen >= nMsgSize) {
                        mbb.position(0);
                    } else {
                        mbb.position(bbLen);
                    }
                } else {
                    break;
                }
            } else {
                mbb.position(bbLen);

                break;
            }
        }
    }

    public synchronized byte[] pop() {
        if (mArrayList.size() == 0) {
            return null;
        }

        byte[] b = mArrayList.get(0);
        mArrayList.remove(b);

        return b;
    }

    public synchronized void clear() {
        mArrayList.clear();
    }

    public synchronized int size() {
        return mArrayList.size();
    }
}
